/*
    订阅客户端联调
*/

#include "../../src/client/connection.hpp"
#include "../../src/common/logger.hpp"

void messageHandler(const mq::Channel::ChannelPtr& channel_pr, const std::string& consumer_tag, const mq::BasicProperties* properties, const std::string& body)
{
    // 1. 处理消息
    INF_LOG("receive message, consumer tag: %s, body: %s, message id: %s, routing key: %s\n", 
        consumer_tag.c_str(), body.c_str(), properties->id().c_str(), properties->routing_key().c_str());

    // 2. 确认消息
    channel_pr->ack(properties->id());
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        INF_LOG("usage: command queue_name\n");
        return -1;
    }

    // 1. 创建异步工作线程
    mq::AsyncWorker::AsyncWorkerPtr async_worker_ptr = std::make_shared<mq::AsyncWorker>();

    // 2. 创建连接对象
    mq::Connection::ConnectionPtr connection_ptr = std::make_shared<mq::Connection>(async_worker_ptr, 8080, "127.0.0.1");

    // 3. 打开信道，并获取对象
    mq::Channel::ChannelPtr channel_ptr = connection_ptr->openChannel();

    // 4. 通过信道发起服务
    // 4.1 声明交换机
    // bool ret = channel_ptr->declareExchanger("exchanger1", mq::ExchangerType::FANOUT, true, false, {}); // 广播类型
    // bool ret = channel_ptr->declareExchanger("exchanger1", mq::ExchangerType::DIRECT, true, false, {}); // 直接交换
    bool ret = channel_ptr->declareExchanger("exchanger1", mq::ExchangerType::TOPIC, true, false, {}); // 主题交换
    if(!ret)
        INF_LOG("declare exchanger failed\n");

    // 4.2 声明队列
    ret = channel_ptr->declareMsgQueue("queue1", true, false, false, {});
    if(!ret)
        INF_LOG("declare msg queue1 failed\n");
    ret = channel_ptr->declareMsgQueue("queue2", true, false, false, {});
    if(!ret)
        INF_LOG("declare msg queue2 failed\n");
    
    // 4.3 绑定队列
    ret = channel_ptr->bind("exchanger1", "queue1", "queue1");
    if(!ret)
        INF_LOG("bind msg queue1 failed\n");
    ret = channel_ptr->bind("exchanger1", "queue2", "news.music.#");
    if(!ret)
        INF_LOG("bind msg queue2 failed\n");
    

    // 4.4 订阅队列
    auto cb = std::bind(messageHandler, channel_ptr, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    ret = channel_ptr->consume("consumer1", argv[1], false, cb);
    if(!ret)
        INF_LOG("consume failed\n");
    while(true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    // 5. 关闭信道
    connection_ptr->closeChannel(channel_ptr);
    if(!ret)
        INF_LOG("close channel failed\n");

    return 0;
}